import sys
sys.path.append(sys.path[0] + "/../interpreter")
from llvmhelper import llvmHelper
from customExceptions import *
from functionBinding import functionBinding
from functionDef import functionDef
from Return import Return
from builtin import *
from varRef import varRef
from expression import environment
from scope import *

sys.path.append(sys.path[0] + "/../parser")
from StaticPass import *

class astToLLVM:
	def __init__(self,program, debug = False, printout = True):
		self.program = program
		self.helper = llvmHelper(debug)
		self.printout = printout
		
	def outputLLVM(self):
		
		try:
			#STATIC PASS!!!! XOR!
			
			#sketchy, but let's see...
			scopeContents = self.program.getContents()
			scopeContents = functionBinding([ functionDef("plus", ["a","b"], scope(Return(plus(varRef("a"),varRef("b"))))),
														 functionDef("minus", ["a","b"], Return(minus(varRef("a"),varRef("b")))),
														 functionDef("mult", ["a","b"], Return(mult(varRef("a"),varRef("b")))),
														 functionDef("div", ["a","b"], Return(div(varRef("a"),varRef("b")))),
														 functionDef("lessThan", ["a","b"], Return(lessThan(varRef("a"),varRef("b")))),
														 functionDef("equals", ["a","b"], Return(equals(varRef("a"),varRef("b")))),
														 functionDef("greatThan", ["a","b"], Return(greatThan(varRef("a"),varRef("b")))),
														 functionDef("lessEq", ["a","b"], Return(lessEq(varRef("a"),varRef("b")))),
														 functionDef("greatEq", ["a","b"], Return(greatEq(varRef("a"),varRef("b")))),
														 functionDef("and", ["a","b"], Return(and_(varRef("a"),varRef("b")))),
														 functionDef("or", ["a","b"], Return(or_(varRef("a"),varRef("b")))),
														 functionDef("not", ["a"], Return(not_(varRef("a")))),
														 functionDef("strlen", ["str"], Return(strlen(varRef("str")))),
														 functionDef("substr", ["str", "s", "e"], Return(substr(varRef("str"),varRef("s"),varRef("e")))),
														 functionDef("strEq", ["str1", "str2"],Return(strEq(varRef("str1"),varRef("str2")))),
														 functionDef("strLess", ["str1", "str2"],Return(strLess(varRef("str1"),varRef("str2")))),
														 functionDef("intQ", ["a"], Return(intQ(varRef("a")))),
														 functionDef("boolQ", ["a"], Return(boolQ(varRef("a")))),
														 functionDef("floatQ", ["a"], Return(floatQ(varRef("a")))),
														 functionDef("voidQ", ["a"], Return(voidQ(varRef("a")))),
														 functionDef("stringQ", ["a"], Return(stringQ(varRef("a")))),
														 functionDef("instanceof", ["obj","val"],Return(instanceof(varRef("obj"),varRef("val")))),
														 functionDef("closureQ", ["a"], Return(closureQ(varRef("a")))),
														 functionDef("plainQ", ["a"], Return(plainQ(varRef("a")))),
														 functionDef("printOut", ["a"], printOut(varRef("a"))),
														 functionDef("readLine", [], Return(readLine()))
													], scopeContents)
			self.program.setContents(scopeContents)
			self.program.setFunctionScope()
		
			
			
			staticAST = StaticPass(self.program, self.helper)
			staticAST.run()
			self.program.toLLVM(self.helper)
			if(self.printout):
				print self.helper.getTextSegment()
			else:
				return self.helper.getTextSegment()
		except GeneralException, g:
			print "\n\nERROR:\n",str(g)
